package cn.tataben.database;

import android.content.Context;

import java.io.File;
import java.io.IOException;
import java.util.List;

import cn.tataben.database.selector.Selector;

/**
 * 数据库工具
 * @author tataben
 */
public final class DBKit implements DB.CreateListener, DB.UpgradeListener {

    private DB db;
    private static DBKit util;
    private DatabaseListener listener;

    /**
     * 安装数据库
     * @return
     */
    public static synchronized DBKit install(Context context, int version, String name, String pwd, DatabaseListener listener) {
        if (util == null) {
            util = new DBKit(context, version, name, pwd, listener);
        }
        return util;
    }

    /**
     * 获取实例
     * @return
     */
    public static DBKit instance() {
        return util;
    }

    /**
     * 注销数据库
     */
    public static void uninstall(){
        if (util != null) {
            util.close();
            util = null;
        }
    }

    private DBKit(Context context, int version, String name, String pwd, DatabaseListener listener) {
        this.listener = listener;
        File dir = context.getDatabasePath(File.separator);
        if (File.separator.equals(dir.getPath())){
            dir = new File(context.getFilesDir(), "database");
        }
        db = new DB(new DB.Config().setDbName(name + ".db").setDbVersion(version)
                .setDbDir(dir).setPassword(pwd).setDbCreateListener(this).setDbUpgradeListener(this));
    }

    @Override
    public void onUpgrade(DB db, int oldVersion, int newVersion) {
        try {
            listener.upgrade(this, oldVersion, newVersion);
        } catch (Exception e) {
            Logger.e(e.getMessage(), e);
        }
    }

    @Override
    public void onCreated(DB db) {
        try {
            if (listener != null) {
                listener.create(this);
            }
        } catch (Throwable e) {
            Logger.e(e.getMessage(), e);
        }
    }


    /**
     * 关闭数据库
     */
    public void close(){
        try {
            if (db != null) {
                db.close();
                db = null;
            }
        } catch (IOException e) {
            Logger.e(e.getMessage(), e);
        }
    }

    /**
     * 保存或更新
     * @param entity list<T> 或 T
     * @throws Exception
     */
    public void saveOrUpdate(Object entity) {
        try {
            db.saveOrUpdate(entity);
        } catch (Exception e) {
            Logger.e(e.getMessage(), e);
        }
    }

    /**
     * 根据ID删除
     * @param entityType
     * @param id
     * @throws Exception
     */
    public void deleteById(Class<?> entityType, Object id) {
        try {
            db.deleteById(entityType, id);
        } catch (Exception e) {
            Logger.e(e.getMessage(), e);
        }
    }

    /**
     * 删除
     * @param entity list<T> 或 T
     * @throws Exception
     */
    public void delete(Object entity) {
        try {
            db.deleteWithoutTransaction(entity);
        } catch (Exception e) {
            Logger.e(e.getMessage(), e);
        }
    }

    /**
     * 清空表
     * @throws Exception
     */
    public void clear(Class<?> entityType) {
        try {
            db.clearWithoutTransaction(entityType);
        } catch (Exception e) {
            Logger.e(e.getMessage(), e);
        }
    }

    /**
     * 根据ID查询
     * @param entityType
     * @param id
     * @param <T>
     * @return
     */
    public <T> T findById(Class<T> entityType, Object id) {
        try {
            return db.findById(entityType, id);
        } catch (Exception e) {
            Logger.e(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 查询所有记录
     * @param entityType
     * @param <T>
     * @return
     */
    public <T> List<T> findAll(Class<T> entityType) {
        try {
            return db.findAll(entityType);
        } catch (Exception e) {
            Logger.e(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 条件查询
     * @param entityType
     * @param <T>
     * @return
     */
    public <T> Selector<T> selector(Class<T> entityType) {
        try {
            return db.selector(entityType);
        } catch (Exception e) {
            Logger.e(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 事务
     * @param listener
     */
    public void inTransaction(TransactionListener listener) {
        try {
            db.beginTransaction();
            listener.transaction(this);
            db.setTransactionSuccessful();
        } catch (Exception e) {
            Logger.e(e.getMessage(), e);
        } finally {
            db.endTransaction();
        }
    }

    /**
     * 是否是表对象
     * @param entityType
     * @return
     */
    public boolean isTable(Class<?> entityType){
        return db.isTable(entityType);
    }

    /**
     * TODO 事务回调
     * @author tataben
     */
    public interface TransactionListener {
        /**
         * 事务
         * @param kit
         * @throws Exception
         */
        void transaction(DBKit kit)throws Exception;
    }

    /**
     * 数据库结构变动
     * @author tataben
     */
    public interface DatabaseListener {
        /**
         * 新创建数据库
         * @param kit
         * @throws Exception
         */
        void create(DBKit kit) throws Exception;

        /**
         * 数据库有变动
         * @param kit
         * @param old
         * @param now
         * @throws Exception
         */
        void upgrade(DBKit kit, int old, int now) throws Exception;
    }

}